﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

using LowLevelGraphics;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// This provides an edge detection filter.
    /// </summary>
    public class ColorEdgeDetection : BaseForeBackgroundColorFilter
    {
        protected int m_nThreshold = 25;
        protected Color m_EdgeColor = Color.White;
        protected int m_nSquaredThreshold = -1;
        protected bool m_bSetBackgroundColor = false;

        /// <summary>
        /// Initializes a new instance of the <see cref="ColorEdgeDetection"/> class.
        /// </summary>
        public ColorEdgeDetection()
        {
            Threshold = m_nThreshold; //Do this to square
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ColorEdgeDetection"/> class.
        /// </summary>
        public ColorEdgeDetection(int _nThreshold, Color _detectionColor)
        {
            Threshold = _nThreshold; //Do this to square value
            m_EdgeColor = _detectionColor;
        }

        /// <summary>
        /// Gets or sets a value indicating whether [set background color].
        /// </summary>
        /// <value><c>true</c> if [set background color]; otherwise, <c>false</c>.</value>
        public bool SetBackgroundColor
        {
            get { return m_bSetBackgroundColor; }
            set { m_bSetBackgroundColor = value; }
        }

        /// <summary>
        /// Gets or sets the threshold.
        /// </summary>
        /// <value>The threshold.</value>
        public int Threshold
        {
            get { return m_nThreshold; }
            set
            {
                m_nThreshold = value;
                m_nSquaredThreshold = m_nThreshold * m_nThreshold;
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ColorEdgeDetection"/> class.
        /// </summary>
        /// <param name="_colorEdgeDetection">The _color edge detection.</param>
        internal ColorEdgeDetection(ColorEdgeDetection _colorEdgeDetection)
        {
        }

        /// <summary>
        /// Does basic edge detection on an image
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns>A bitmap which has the edges drawn on it</returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap tempBitmap =(UnsafeBitmap)_bitmap.Clone();
            UnsafeBitmap resultBitmap = _bitmap;

            int nWidth = resultBitmap.Width;
            int nHeight = resultBitmap.Height;

            Color currentColor = Color.Transparent;
            Color colorTemp = Color.Transparent;

            bool bEdgeSet = false;

            for (int x = 0; x < nWidth; ++x)
            {
                for (int y = 0; y < nHeight; ++y)
                {
                    bEdgeSet = false;
                    if (m_bSetBackgroundColor)
                    {
                        resultBitmap.SetPixel(x, y, m_ColorBackground);
                    }

                    currentColor = resultBitmap.GetPixel(x, y);
                    if (y < nHeight - 1 && x < nWidth - 1)
                    {
                        colorTemp = resultBitmap.GetPixel(x + 1, y + 1);
                        if (((currentColor.R - colorTemp.R) * (currentColor.R - colorTemp.R)) +
                            ((currentColor.G - colorTemp.G) * (currentColor.G - colorTemp.G)) +
                            ((currentColor.B - colorTemp.B) * (currentColor.B - colorTemp.B)) > m_nSquaredThreshold)
                        {
                            resultBitmap.SetPixel(x, y, m_EdgeColor);
                        }
                        bEdgeSet = true;
                    }
                    if (y < nHeight - 1 && !bEdgeSet)
                    {
                        colorTemp = resultBitmap.GetPixel(x, y + 1);
                        if (((currentColor.R - colorTemp.R) * (currentColor.R - colorTemp.R)) +
                            ((currentColor.G - colorTemp.G) * (currentColor.G - colorTemp.G)) +
                            ((currentColor.B - colorTemp.B) * (currentColor.B - colorTemp.B)) > m_nSquaredThreshold)
                        {
                            resultBitmap.SetPixel(x, y, m_EdgeColor);
                        }
                        bEdgeSet = true;
                    }
                    if (x < nWidth - 1 && !bEdgeSet)
                    {
                        colorTemp = resultBitmap.GetPixel(x + 1, y);
                        if (((currentColor.R - colorTemp.R) * (currentColor.R - colorTemp.R)) +
                            ((currentColor.G - colorTemp.G) * (currentColor.G - colorTemp.G)) +
                            ((currentColor.B - colorTemp.B) * (currentColor.B - colorTemp.B)) > m_nSquaredThreshold)
                        {
                            resultBitmap.SetPixel(x, y, m_EdgeColor);
                        }
                        bEdgeSet = true;
                    }
                }
            }
            tempBitmap.Dispose();
            return _bitmap;
        }
        /// <summary>
        /// This is used to clone a filter, each filter must implement it's own clone functionality
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new ColorEdgeDetection(this);
        }
    }
}
